package cmd

import (
	"gitee.com/whilew/gmodel/internal/cfg"
	"gitee.com/whilew/gmodel/internal/gen"
	"gitee.com/whilew/gmodel/internal/util"
	"github.com/spf13/cobra"
	"os"
	"path/filepath"
	"strings"
)

var (
	genRemovePrefix     = genCmd.Flags().StringP("remove_prefix", "", cfg.GetCfg("remove_prefix"), "remove table prefix")
	genDbType           = genCmd.Flags().StringP("db_type", "", cfg.GetCfg("db_type"), "database type: mysql")
	genLink             = genCmd.Flags().StringP("link", "l", cfg.GetCfg("link"), "database link")
	genOutputDir        = genCmd.Flags().StringP("output_dir", "o", cfg.GetCfg("output_dir"), "相对于项目根目录的输出目录,默认为model")
	genD                = genCmd.Flags().BoolP("d", "d", false, "在当前目录生成model文件，优先级>output_dir")
	genClearAll         = genCmd.Flags().BoolP("clear_all", "", false, "clear all model files")
	genTableTemplate    = genCmd.Flags().StringP("table_template", "", cfg.GetCfg("table_template"), "table template")
	genFileNameTemplate = genCmd.Flags().StringP("file_name_template", "", cfg.GetCfg("file_name_template"), "model file name template")
	genForce            = genCmd.Flags().BoolP("force", "f", false, "force generate model file")
	genWithoutP         = cfg.GetCfg(cfg.EnvWithoutPCfgKey)
	genWithout          = cfg.GetCfg(cfg.EnvWithoutCfgKey)
)

var genCmd = &cobra.Command{
	Use:   "gen",
	Short: "generate database model",
}

func init() {
	genCmd.Run = genRun
	rootCmd.AddCommand(genCmd)
}

func genRun(cmd *cobra.Command, args []string) {
	input := gen.GenInput{
		RemovePrefix:     *genRemovePrefix,
		Link:             *genLink,
		OutputDir:        *genOutputDir,
		TableTemplate:    *genTableTemplate,
		FileNameTemplate: *genFileNameTemplate,
	}
	checkGenInput(&input)
	if *genClearAll {
		// todo 给用户确认是否删除
		// 将会删除xxx目录下所有文件，是否确认。
	}

	db, err := util.ConnectDb(*genDbType, *genLink)
	if err != nil {
		util.Fatalf("gmodel: 获取db实例异常 %v", err)
	}

	tables, err := db.GetTables()
	if err != nil {
		util.Fatalf("gmodel: 获取tables异常 %v", err)
	}

	if genWithout != "" {
		without := strings.Split(genWithout, ",")
		var ttables []*util.Table
		for _, t := range tables {
			isHave := false
			for _, w := range without {
				if t.Name == w {
					isHave = true
					break
				}
			}
			if !isHave {
				ttables = append(ttables, t)
			}
		}
	}

	if genWithoutP != "" {
		without := strings.Split(genWithoutP, ",")
		var ttables []*util.Table
		for _, t := range tables {
			isHave := false
			for _, w := range without {
				if strings.HasPrefix(t.Name, w) {
					isHave = true
					break
				}
			}
			if !isHave {
				ttables = append(ttables, t)
			}
		}
		tables = ttables
	}

	if len(args) > 0 {
		var ttables []*util.Table
		for _, t := range args {
			for _, table := range tables {
				if t == table.Name {
					ttables = append(ttables, table)
					break
				}
			}
		}
		tables = ttables
	}

	for _, t := range tables {
		for _, f := range t.Fields {
			if f.Name == "id" {
				f.Type = "uint64"
			}
			if f.Name == "deleted_at" {
				f.Type = "*time.Time"
			}
		}
	}

	// todo 比对数据库表结构和model文件，如果有变化则提示用户是否更新
	err = gen.GenEntity(&input, tables, *genForce)
	if err != nil {
		util.Fatalf("gmodel: %v", err)
	}
}

func checkGenInput(input *gen.GenInput) {
	if input.Link == "" {
		util.Fatalf("gmodel: link is required")
	}
	if *genD {
		input.OutputDir, _ = os.Getwd()
	} else {
		if input.OutputDir == "" {
			input.OutputDir = "model"
		}
		projDir, err := util.GetProjRootDir()
		if err != nil {
			util.Fatalf("gmodel: cannot get projDir: %v,please set [-output_dir] param", err)
		}
		input.OutputDir = filepath.Join(projDir, input.OutputDir)
	}

	if *genDbType == "" {
		*genDbType = "mysql"
	}

	if input.FileNameTemplate == "" {
		input.FileNameTemplate = gen.DefaultFileNameTemplate
	}
	if input.TableTemplate == "" {
		input.TableTemplate = gen.DefaultTableTemplate
	}
}
